package com.inetools.gwetons.client;

import java.util.LinkedHashSet;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;

/**
 * Handler to track attention on object. 
 * Tracking behavior can be changed by setting trackFocus flag and trackMouse flag like followings:
 * When trackFocus flag is true, and the object adapted this get selected (such as got cursor), 
 * gotAttention method of registered AttentionTrackerListener object will be triggered. 
 * And isHoldingAttention method return true. If the object lost focus, then lostAttention of 
 * registered AttentionTrackerListener object will be triggered. And isHoldingAttention method return false.
 * When trackMouse flag is true, and the mouse pointer hovers over the object adapted this, 
 * gotAttention method of registered AttentionTrackerListener object will be triggered. 
 * And isHoldingAttention method return true. If the mouse pointer moves away from the object adapted this, 
 * then lostAttention of registered AttentionTrackerListener object will be triggered. And 
 * isHoldingAttention method return false.
 * When trackFocus flag and trackMouse flag is true, "AND" combines of both behaviors. 
 * @author ay
 *
 */
public class AttentionTracker 
implements MouseOverHandler, MouseOutHandler, BlurHandler, FocusHandler {
	
	// For event issuing --------------------------------------------------------------------------
	public interface AttentionTrackerListener {
		public void gotAttention();
		public void lostAttention();
	}
	protected LinkedHashSet<AttentionTrackerListener> attentionTrackerListenerLinkedHashSet = 
		new LinkedHashSet<AttentionTrackerListener>();
	public boolean addAttentionTrackerListener( AttentionTrackerListener attentionTrackerListener) {
		if ( attentionTrackerListener == null) return false;
		return attentionTrackerListenerLinkedHashSet.add( attentionTrackerListener);
	}
	public boolean removeAttentionTrackerListener( AttentionTrackerListener attentionTrackerListener) {
		return attentionTrackerListenerLinkedHashSet.remove( attentionTrackerListener);
	}
	protected void fireGotAttentionEvent() {
		for( AttentionTrackerListener attentionTrackerListener : attentionTrackerListenerLinkedHashSet) {
			attentionTrackerListener.gotAttention();
		} // for
	}
	protected void fireLostAttentionEvent() {
		for( AttentionTrackerListener attentionTrackerListener : attentionTrackerListenerLinkedHashSet) {
			attentionTrackerListener.lostAttention();
		} // for
	}
	// --------------------------------------------------------------------------------------------
	
	private boolean trackFocus = false;
	public boolean isTrackFocus() {
		return trackFocus;
	}
	public void setTrackFocus(boolean trackFocus) {
		this.trackFocus = trackFocus;
	}

	private boolean trackMouse = true;
	public boolean isTrackMouse() {
		return trackMouse;
	}
	public void setTrackMouse(boolean trackMouse) {
		this.trackMouse = trackMouse;
	}

	public AttentionTracker() {
	}
	public AttentionTracker( boolean trackFocus, boolean trackMouse) {
		this.trackFocus = trackFocus;
		this.trackMouse = trackMouse;
	}
	
	protected boolean holdingMouseFlag = false;	
	protected boolean holdingFocusFlag = false;
	
	public boolean isHoldingAttention() {
		if ( trackFocus && trackMouse) {
			return ( holdingMouseFlag || holdingFocusFlag);
		}
		else if ( trackFocus) return holdingFocusFlag;
		else if ( trackMouse) return holdingMouseFlag;
		return false;
	}
	
	@Override
	public void onMouseOver(MouseOverEvent event) {
		if ( trackMouse && !isHoldingAttention()) fireGotAttentionEvent();
		holdingMouseFlag = true;
	}
	@Override
	public void onMouseOut(MouseOutEvent event) {
		holdingMouseFlag = false;
		if ( trackMouse && !isHoldingAttention()) fireLostAttentionEvent();
	}

	@Override
	public void onFocus(FocusEvent event) {
		if ( trackFocus && !isHoldingAttention()) fireGotAttentionEvent();
		holdingFocusFlag = true;
	}
	@Override
	public void onBlur(BlurEvent event) {
		holdingFocusFlag = false;
		if ( trackFocus && !isHoldingAttention()) fireLostAttentionEvent();
	}
} // public class AttentionTracker
